package com.ruoyi.business.appuser.controller;

import cn.hutool.core.lang.Validator;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruoyi.business.appuser.service.WeiXinService;
import com.ruoyi.business.appuser.vo.Code2Session;
import com.ruoyi.business.appuser.vo.WeiXinLoginVo;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.framework.web.service.SysLoginService;
import com.ruoyi.framework.web.service.SysPermissionService;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.system.service.ISysUserService;
import com.zhhy.tool.utils.IntegerUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.spec.AlgorithmParameterSpec;
import java.util.List;

/**
 * 微信控制层
 *
 * @author Tellsea
 * @date 2021/11/09
 */
@Slf4j
@Api(value = "微信API", tags = {"微信API"})
@RestController
@RequestMapping("/app/weiXin")
public class AuWeiXinController {

    @Autowired
    private ISysUserService userService;
    @Autowired
    private SysLoginService loginService;
    @Autowired
    private WeiXinService weiXinService;
    @Autowired
    private SysPermissionService permissionService;
    @Autowired
    private TokenService tokenService;

    @ApiOperation("登录预检查")
    @GetMapping("beforeLogin")
    public AjaxResult beforeLogin() {
        return AjaxResult.success("登录成功");
    }

    @ApiOperation("微信用户登录")
    @PostMapping("login")
    public AjaxResult login(@RequestBody WeiXinLoginVo dto) {
        Code2Session code2Session = weiXinService.code2Session(dto.getCode());
        if (StringUtils.isNotEmpty(code2Session.getOpenId())) {
            // 解析电话号码
            String phoneNumber;
            byte[] byEncrypdata = Base64.decodeBase64(dto.getEncryptedData());
            byte[] byIvdata = Base64.decodeBase64(dto.getIv());
            byte[] bySessionkey = Base64.decodeBase64(code2Session.getSessionKey());
            AlgorithmParameterSpec ivSpec = new IvParameterSpec(byIvdata);
            try {
                SecretKeySpec keySpec = new SecretKeySpec(bySessionkey, "AES");
                Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
                cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
                String phoneResult = new String(cipher.doFinal(byEncrypdata), StandardCharsets.UTF_8);
                JSONObject phoneObject = JSONObject.parseObject(phoneResult);
                phoneNumber = phoneObject.getString("phoneNumber");
            } catch (Exception e) {
                e.printStackTrace();
                return AjaxResult.error("手机号码解密失败");
            }
            // 根据openId查询是否存在这个用户
            List<SysUser> list = userService.list(new LambdaQueryWrapper<SysUser>().eq(SysUser::getOpenId, code2Session.getOpenId())
                    .or().eq(SysUser::getUserName, phoneNumber).or().eq(SysUser::getPhonenumber, phoneNumber));
            AjaxResult ajax = AjaxResult.success();
            if (CollectionUtils.isEmpty(list)) {
                // 添加新用户
                String defaultPassword = "123456";
                SysUser user = new SysUser()
                        .setOpenId(code2Session.getOpenId())
                        .setUserName(phoneNumber)
                        .setNickName(dto.getNickName())
                        .setDeptId(0L)
                        .setPassword(defaultPassword)
                        .setPhonenumber(phoneNumber)
                        .setAvatar(dto.getAvatarUrl());
                if (IntegerUtils.eq(dto.getGender(), 0)) {
                    user.setSex("2");
                } else if (IntegerUtils.eq(dto.getGender(), 1)) {
                    user.setSex("0");
                } else if (IntegerUtils.eq(dto.getGender(), 2)) {
                    user.setSex("1");
                }
                if (UserConstants.NOT_UNIQUE.equals(userService.checkUserNameUnique(user.getUserName()))) {
                    return AjaxResult.error("手机号已被注册");
                } else if (Validator.isNotEmpty(user.getPhonenumber())
                        && UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique(user))) {
                    return AjaxResult.error("手机号已被使用");
                }
                user.setCreateBy(SecurityUtils.getUsername());
                user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
                // 默认给角色用户
                user.setRoleIds(new Long[]{1L});
                userService.insertUser(user);
                String token = loginService.login(user.getUserName(), defaultPassword);
                ajax.put(Constants.TOKEN, token);
                return ajax;
            } else if (list.size() == 1) {
                // 更新用户信息：这里查询出的一个信息，可能是openId、userName、phonenumber三个字段其中某个查出来的
                SysUser sysUser = list.get(0);
                sysUser.setNickName(dto.getNickName());
                sysUser.setAvatar(dto.getAvatarUrl());
                if (IntegerUtils.eq(dto.getGender(), 0)) {
                    sysUser.setSex("2");
                } else if (IntegerUtils.eq(dto.getGender(), 1)) {
                    sysUser.setSex("0");
                } else if (IntegerUtils.eq(dto.getGender(), 2)) {
                    sysUser.setSex("1");
                }
                if (StringUtils.isEmpty(sysUser.getOpenId())) {
                    sysUser.setOpenId(code2Session.getOpenId());
                }
                userService.updateById(sysUser);
                SysUser user = userService.selectUserByUserName(sysUser.getUserName());
                LoginUser loginUser = new LoginUser(user, permissionService.getMenuPermission(user));
                String token = tokenService.createToken(loginUser);
                ajax.put(Constants.TOKEN, token);
                return ajax;
            } else {
                return AjaxResult.error("用户信息异常，存在多个openId或电话号码");
            }
        } else {
            return AjaxResult.error(code2Session.getErrMsg());
        }
    }
}
